#include"memory_space.h"
#include<unordered_map>
#include<iostream>

//TODO:片上内存AM,SM,GSM均有固定的起始地址，故可以修改设计，修改为线性映射，提高效率
//线性映射即addr-起始地址偏移的方式获取该块存储内部对应的偏移

// std::unordered_map<addr_size_t, int> *address_index_map
//                                         = new std::unordered_map<addr_size_t, int>(1024);

// inline int get_addr_index(addr_size_t addr) {
//     auto it = address_index_map->find(addr);
//     if (it != address_index_map->end()) {
//         return it->second;
//     } else {
//         return -1;
//     }
// }

// inline void store_addr_index(addr_size_t addr, int index) {
//     address_index_map->insert(std::make_pair(addr, index));
// }

// char memory::load_1_byte(addr_size_t addr) {
//     int index = get_addr_index(addr);
//     if (index >= 0) {
//         return this->storage->at(index);
//     } else {
//         throw "<1 byte load> memory access address is invalid!";
//     }
// }

// short memory::load_2_bytes(addr_size_t addr) {
//     int index = get_addr_index(addr);
//     if (index >= 0) {
//         short res = this->storage->at(index + 1);
//         res = res << 8;
//         res = res | this->storage->at(index);
//         return res;
//     } else {
//         throw "<2 bytes load> memory access address is invalid!";
//     }
// }

// int memory::load_4_bytes(addr_size_t addr) {
//     int index = get_addr_index(addr);
//     if (index >= 0) {
//         int res = this->load_2_bytes(index + 2);
//         res = res << 16;
//         res = res | this->load_2_bytes(index);
//         return res;
//     } else {
//         throw "<4 bytes load> memory access address is invalid!";
//     }
// }

// long long int memory::load_8_bytes(addr_size_t addr) {
//     int index = get_addr_index(addr);
//     if (index >= 0) {
//         long long int res = this->load_4_bytes(index + 4);
//         res = res << 16;
//         res = res | this->load_4_bytes(index);
//         return res;
//     } else {
//         throw "<8 bytes load> memory access address is invalid!";
//     }
// }

// bool memory::store_1_byte(addr_size_t addr, char value) {
//     this->storage->push_back(value);
//     store_addr_index(addr, this->storage->size() - 1);
//     return true;
// }

// bool memory::store_2_bytes(addr_size_t addr, short value) {
//     char low_byte = value & 0xFF;
//     char high_byte = (value >> 8) & 0xFF;
//     store_1_byte(addr, low_byte);
//     store_1_byte(addr + 1, high_byte);
//     return true;
// }

// bool memory::store_4_bytes(addr_size_t addr, int value) {
//     short low_half = value & 0xFFFF;
//     short high_half = (value >> 16) & 0xFFFF;
//     store_2_bytes(addr, low_half);
//     store_2_bytes(addr + 2, high_half);
//     return true;
// }

// bool memory::store_8_bytes(addr_size_t addr, long long int value) {
//     int low_int = value & 0xFFFFFFFF;
//     int high_int = (value >> 32) & 0xFFFFFFFF;
//     store_4_bytes(addr, low_int);
//     store_4_bytes(addr + 4, high_int);
//     return true;
// }


//得到在该块模拟内存内部，应以多少偏移去读取数据
inline uint64_t memory::get_addr_offset(addr_size_t addr) {
    return addr - this->offset;
}

uint8_t memory::load_1_byte(addr_size_t addr) {
    int index = get_addr_offset(addr);
    if (index >= 0) {
        //memory_space为char*，直接读取偏移处的一个元素即可
        return this->memory_space[index];
    } else {
        throw "<1 byte load> memory access address is invalid!";
    }
}

uint16_t memory::load_2_bytes(addr_size_t addr) {
    int index = get_addr_offset(addr);
    if (index >= 0) {
        //转化为short，读取出2个字节
        return *(reinterpret_cast<uint16_t*>(this->memory_space + index));
    } else {
        throw "<2 bytes load> memory access address is invalid!";
    }
}

uint32_t memory::load_4_bytes(addr_size_t addr) {
    int index = get_addr_offset(addr);
    if (index >= 0) {
        //转化为int，读取出4个字节
        return *(reinterpret_cast<uint32_t*>(this->memory_space + index));
    } else {
        throw "<4 bytes load> memory access address is invalid!";
    }
}

uint64_t memory::load_8_bytes(addr_size_t addr) {
    int index = get_addr_offset(addr);
    std::cout << "Loading 8 bytes from address: " << addr << ", internal index: " << index << std::endl;
    if (index >= 0) {
        //转化为long long int，读取出8个字节
        std::cout << "Data loaded: " << *(reinterpret_cast<long long int*>(this->memory_space + index)) << std::endl;
        return *(reinterpret_cast<uint64_t*>(this->memory_space + index));
    } else {
        std::cout << "Error: Invalid memory access address for 8 bytes load." << std::endl;
        throw "<8 bytes load> memory access address is invalid!";
    }
}

bool memory::store_1_byte(addr_size_t addr, uint8_t value) {
    int index = get_addr_offset(addr);
    this->memory_space[index] = value;
    return true;
}

bool memory::store_2_bytes(addr_size_t addr, uint16_t value) {
    int index = get_addr_offset(addr);
    *(reinterpret_cast<uint16_t*>(this->memory_space + index)) = value;
    return true;
}

bool memory::store_4_bytes(addr_size_t addr, uint32_t value) {
    int index = get_addr_offset(addr);
    *(reinterpret_cast<uint32_t*>(this->memory_space + index)) = value;
    return true;
}

bool memory::store_8_bytes(addr_size_t addr, uint64_t value) {
    int index = get_addr_offset(addr);
    *(reinterpret_cast<uint64_t*>(this->memory_space + index)) = value;
    return true;
}


/*以下为专为AM设计的向量寄存器内存存取接口，一次可操作一组16个寄存器*/

inline uint64_t signed_inflation(int value) {
    int flag = value & 0x80000000;
    uint64_t temp = 0;
    double res;
    if (flag != 0) {
        //value的最高位为1，高32位填充1
        temp = 0xFFFFFFFF00000000 | value;
    } else {
        //value的最高位为0，高32位填充0
        temp = 0x0000000000000000 | value;
    }
    std::memcpy(&res, &temp, sizeof(res));
    return res;
}

inline uint64_t unsigned_inflation(int value) {
    uint64_t temp = 0x0000000000000000 | value;
    double res;
    std::memcpy(&res, &temp, sizeof(res));
    return res;
}

std::vector<uint64_t>* V_memory::load_hw_vector(addr_size_t addr) {
    std::vector<uint64_t>* res = new std::vector<uint64_t>(16, 0);
    int index = get_addr_offset(addr);
    for (int i = 0; i < 16; i++) {
        res->at(i) = signed_inflation(this->load_4_bytes(addr + i * 4));
    }
    return res;
}

//无符号半字加载，我的理解是高32位补0
std::vector<uint64_t>* V_memory::load_hwu_vector(addr_size_t addr) {
    std::vector<uint64_t>* res = new std::vector<uint64_t>(16, 0);
    int index = get_addr_offset(addr);
    for (int i = 0; i < 16; i++) {
        res->at(i) = unsigned_inflation(this->load_4_bytes(addr + i * 4));
    }
    return res;
}

std::vector<uint64_t>* V_memory::load_w_vector(addr_size_t addr) {
    std::vector<uint64_t>* res = new std::vector<uint64_t>(16, 0);
    int index = get_addr_offset(addr);
    for (int i = 0; i < 16; i++) {
        res->at(i) = this->load_8_bytes(addr + i * 8);
    }
    return res;
}

bool V_memory::store_hw_vector(addr_size_t addr, std::vector<uint64_t>* value) {
    int index = get_addr_offset(addr);
    uint32_t temp = 0;
    for (int i = 0; i < 16; i++) {
        //截取寄存器的低32位进行存储
        temp = static_cast<uint32_t>(value->at(i));
        //取寄存器的低32位存入AM
        this->store_4_bytes(addr + i * 4, temp);
    }
    return true;
}

bool V_memory::store_w_vector(addr_size_t addr, std::vector<uint64_t>* value) {
    int index = get_addr_offset(addr);
    for (int i = 0; i < 16; i++) {
        this->store_8_bytes(addr + i * 8, value->at(i));
    }
    return true;
}
